package com.yunhan.security;


import com.yunhan.redis.CacheTime;
import com.yunhan.redis.RedisCache;
import com.yunhan.redis.RedisConstants;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 用户缓存操作类
 * @Description
 * @Author liuzhenkun
 * @Date 2024/12/22
 */
@Component
public class UserCache {
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 设置用户信息到缓存中
     * key1过期时间为1m
     * key2过期时间为2h
     * @param token
     * @param user
     */
    public void setUser(String token, SecurityUser user) {
        String key1 = RedisConstants.buildKey(RedisConstants.Key.USER_TOKEN_KEY1, user.getId(), token);
        String key2 = RedisConstants.buildKey(RedisConstants.Key.USER_TOKEN_KEY2, user.getId(), token);
        redisCache.set(key1, user, CacheTime.Minute.MINUTE_30, TimeUnit.MINUTES);
        redisCache.set(key2, user.getUsername(), CacheTime.Day.DAY_5, TimeUnit.DAYS);
    }


    /**
     * 缓存用户缓存信息
     * key1命中则直接返回，否则查询key2
     * key2未命中则返回null
     * key命中，则根据key值到DB中查询数据，并将查询结果返回，并重置key1和key2的值
     * @param token
     * @return
     */
    public SecurityUser getUser(String token) {
        //step1：从token中解析出用户信息
        String uid = JWTUtils.getUid(token);

        String key1 = RedisConstants.buildKey(RedisConstants.Key.USER_TOKEN_KEY1, uid, token);
        String key2 = RedisConstants.buildKey(RedisConstants.Key.USER_TOKEN_KEY2, uid, token);

        return redisCache.getIfPresent(key1, ()->{
            val username = redisCache.get(key2, String.class);
            if (null == username)
                return null;
            SecurityUser userDetails = (SecurityUser) userDetailsService.loadUserByUsername(username);
            redisCache.set(key2, username, CacheTime.Day.DAY_5, TimeUnit.DAYS);
            return userDetails;
        },CacheTime.Minute.MINUTE_30, TimeUnit.MINUTES ,SecurityUser.class);
    }


}
